
package peerToPeerFacebook.proj;

import java.io.Serializable;


/**
 * This class performs accept friend operation. To use this class do something
 * like this: var a = new AcceptFriendCommand(server, "Foo", "Bar"); a.start(new
 * IResultCallback() {
 * 
 * @Override public void resultCallback(Status status, Serializable result) { //
 *           You will get either status == success on success // or information
 *           about last failure. Caller should probably not care too much about
 *           what failed, // just that it failed. } });
 */
public class AcceptFriendCommand
{
    public static final String FriendFileSuffix = "_friends.txt";
    public static final String PendingFriendRequestsFileSuffix = "_pendingFriendRequests.txt";
    public static final String MessagesFileSuffix = "_messages.txt";

    protected String userName = null;
    protected String friendName = null;
    protected IResultCallback result = null;
    protected boolean userAccepted = false;
    protected boolean friendAccepted = false;
    private String format = "***************";
    RemoteInvoker friendClient;
    RemoteInvoker userClient;

    /**
     * helper method used for checking which flag needs to be enabled in
     * addToFriendList method
     * 
     * @return the username of user who is logged in
     */
    String getUserName()
    {
        return userName;
    }

    /**
     * Constructor for the class
     * 
     * @param userName, the username of the user logged in
     * @param friendName, the name of the friend whose request needs to be
     *            accepted
     * @param userClient the RPCClient of the server where the user account
     *            resides
     * @param friendClient the RPCClient of the server where the friend
     *            account resides
     */
    public AcceptFriendCommand(String userName, String friendName, RemoteInvoker userClient, RemoteInvoker friendClient)
    {
        this.friendName = friendName;
        this.userName = userName;
        this.friendClient = friendClient;
        this.userClient = userClient;
    }

    /**
     * helper method for printing the result of the failed RPC call
     */

    public void printErrorMsg()
    {
        System.out.println(" \n\n" + format + " The requested operation failed " + format +
                           "\n\n");
    }

    protected void acceptFriend(final String friendToAdd, final String forFriend, final RemoteInvoker clientFriendForAdd)
    {
        clientFriendForAdd.invoke(IServerFileIO.GetFileContentsMethodName,
                                     new Serializable[] {forFriend +
                                                         PendingFriendRequestsFileSuffix},
                                     new IResultCallback()
                                     {
                                         @Override
                                         public void resultCallback(Status status,
                                                                    Serializable result)
                                         {
                                             String content = (String) result;
                                             if ((forFriend.equals(getUserName())))
                                                 if ((status == Status.Success) &&
                                                     content != null &&
                                                     content.contains(friendToAdd))
                                                 {
                                                     writePendingFriends((String) result,
                                                                         friendToAdd,
                                                                         forFriend,
                                                                         clientFriendForAdd);
                                                 }
                                                 else
                                                 {
                                                     System.out
                                                             .println("Failed to read file or you are not invited "
                                                                      + "to join.");
                                                     printErrorMsg();
                                                 }
                                             // In case of friend, its possible
                                             // that his pending request doesn't
                                             // contain user's name. So we don't
                                             // need to check for success in
                                             // this case
                                             // We just need to make sure that
                                             // we are invited.
                                             else if (!forFriend.equals(getUserName()))
                                             {
                                                 writePendingFriends((String) result,
                                                                     friendToAdd, forFriend,
                                                                     clientFriendForAdd);
                                             }
                                             else
                                             {
                                                 printErrorMsg();
                                             }
                                         }
                                     });

    }

    protected void writePendingFriends(String currentPendingRequests,
                                       final String friendToAdd, final String forFriend,
                                       final RemoteInvoker clientFriendForAdd)
    {
        final String newPendingRequests =
                currentPendingRequests.replace(friendToAdd + "\r\n", "");
        clientFriendForAdd.invoke(IServerFileIO.PutContentsToFileMethodName,
                                     new Serializable[] {
                                             forFriend + PendingFriendRequestsFileSuffix,
                                             newPendingRequests}, new IResultCallback()
                                     {
                                         @Override
                                         public void resultCallback(Status status,
                                                                    Serializable result)
                                         {
                                             // if (success(status, result))
                                             if (status == Status.Success)
                                                 addToFriendsList(friendToAdd, forFriend,
                                                                  clientFriendForAdd);
                                             else
                                             {
                                                 printErrorMsg();
                                             }
                                         }
                                     });
    }

    protected void addToFriendsList(final String friendToAdd, final String forFriend,
                                    final RemoteInvoker clientFriendForAdd)
    {
        clientFriendForAdd.invoke(IServerFileIO.AppendContentsToFileMethodName,
                                     new Serializable[] {forFriend + FriendFileSuffix,
                                             friendToAdd + "\r\n"}, new IResultCallback()
                                     {
                                         @Override
                                         public void resultCallback(Status status,
                                                                    Serializable result)
                                         {
                                             // if (success(status, result))
                                             if (status == Status.Success)
                                             {
                                                 if (forFriend.equals(getUserName()))
                                                     userAccepted();
                                                 else
                                                     friendAccepted();
                                                 start(status);
                                             }
                                             else
                                             {
                                                  printErrorMsg();
                                             }
                                         }
                                     });
    }

    protected void start(Status status)
    {
        if (!userAccepted)
        {
            acceptFriend(friendName, userName, userClient);
        }
        else if (!friendAccepted)
        {
            acceptFriend(userName, friendName, friendClient);
        }
        else // we are done
        if (status == Status.Success)
        {
            System.out
                    .println("\n\n " + format + "  Friend request got accepted!  " + userName +
                             " and " + friendName + " are friends now! " + format);
        }
        else
        {
            System.out
                    .println(" \n\n" +
                             format +
                             " There was an error processing the request. Friend Request couldn't be accepted. " +
                             format + "\n\n");

        }
    }

    protected void userAccepted()
    {
        userAccepted = true;
    }

    protected void friendAccepted()
    {
        friendAccepted = true;
    }

    /*protected boolean success(Status status, Serializable result)
    {
        if (status != Status.Success)
            this.result.resultCallback(status, result);

        return status != Status.Success;
    }
*/}
